#include "unp.h"

void str_echo(int fd);
void sig_child(int sig);

int main(int argc, char **argv)
{
  int sockfd,connfd;
  struct sockaddr_in svraddr,cliaddr;
  socklen_t clilen;
  pid_t childpid;

  if (argc < 2)
  {
    printf("usage: svr <host> <port>\n");
    exit(-1);
  }

  sockfd = socket(AF_INET,SOCK_STREAM,0);
  memset(&svraddr,0,sizeof(svraddr));
  svraddr.sin_family = AF_INET;
  svraddr.sin_port = htons(atoi(argv[2]));
  inet_pton(AF_INET,argv[1],&svraddr.sin_addr);

  bind(sockfd,(struct sockaddr*)(&svraddr),sizeof(svraddr));
  listen(sockfd,5);

  signal(SIGCHLD,sig_child);

  for (;;)
  {
    clilen = sizeof(cliaddr);
    connfd = accept(sockfd,(struct sockaddr*)(&cliaddr),&clilen);
    childpid = fork();

    if (childpid == 0)
    {
      close(sockfd);
      str_echo(connfd);
      exit(0);
    }

    close(connfd);
  }
}

void str_echo(int fd)
{
  ssize_t n;
  char buf[4096] = {'\0'};

again:
  while ((n=read(fd,buf,sizeof(buf))) > 0)
  {
    write(fd,buf,n);
  }

  if (n < 0 && errno == EINTR)
  {
    goto again;
  }
  else if (n < 0)
  {
    printf("read error:%s\n",strerror(errno));
  }
}

void sig_child(int sig)
{
  pid_t pid;
  int status;

  while ( (pid=waitpid(-1,&status,WNOHANG)) > 0)
  {
    printf("child %d terminated\n",pid);
  }

  return;
}
